// // 1. co 自执行函数(用generator 模拟async await)
// // 2. all
// // 3. race
// // 4. allsettled
// // 5. finally
// // 6. quene
// // 7. promiseQuene
// // 8. promiseQuene 增加cache request
// // 8. 请求重试
// // 9. 实现一个微任务

// function co(gen) {
//     var g = gen()

//     function next(data) {
//         const { done, value } = g.next(data)
//         if (done) return value;
//         if (value.then) {
//             value.then((data) => next(data))
//         } else {
//             next(value)
//         }
//     }
//     next()
// }

// co(function* () {
//     var a = yield Promise.resolve(1)
//     var b = yield Promise.resolve(2)
//     console.log(a + b);
// })


// Promise.myAll = function (promises) {
//     let arr = [];
//     let count = 0;
//     return new Promise((resolve, reject) => {
//         for (let i = 0; i < promises.length; i++) {
//             Promise.resolve(promises[i])
//                 .then((item) => {
//                     arr.push(item)
//                     count++
//                     if (count === promises.length) {
//                         resolve(arr)
//                     }
//                 })
//                 .catch(err => reject(err))
//         }
//     })
// }

// Promise.myAll([
//     Promise.resolve(1),
//     Promise.resolve(2),
//     Promise.resolve(3)
// ]).then(res => console.log(res)).catch(err => console.log(err))



// Promise.myRace = function (promises) {
//     return new Promise((resolve, reject) => {
//         for (let i = 0; i < promises.length; i++) {
//             Promise.resolve(promises[i]).then((item) => {
//                 resolve(item)
//             }).catch(err => reject(err))
//         }
//     })
// }
// Promise.myRace([
//     new Promise((resolve) => setTimeout(resolve, 500, 'one')),
//     new Promise((resolve) => setTimeout(resolve, 100, 'two'))
// ]).then(res => console.log(res)).catch(err => console.error(err))


// Promise.myAllSettled = function (promises) {
//     let newPromises = promises.map(p => {
//         return Promise.resolve(p)
//             .then((item) => ({
//                 status: 'resolved',
//                 value: item
//             })).catch(err => ({
//                 status: 'rejected',
//                 value: err
//             }))
//     })
//     return Promise.all(newPromises)
// }
// Promise.myAllSettled([
//     Promise.resolve(33),
//     new Promise(resolve => setTimeout(resolve, 0, 66)),
//     99,
//     Promise.reject(new Error('err'))
// ]).then(res => console.log(res)).catch(err => console.error(err))


// Promise.prototype.myFinally = function (callback) {
//     let P = this.constructor;

//     return this.then(
//         (val) => P.resolve(callback()).then(() => val),
//         (err) => P.resolve(callback()).then(() => { throw err })
//     )
// }
// Promise.resolve(2).then(res => console.log('done', res)).myFinally(() => console.log('finally done'))


// class Queue {
//     constructor() {
//         this.cacheList = [];
//     }
//     add(fn) {
//         this.cacheList.push(fn)
//         return this
//     }
//     async task() {
//         for (let i = 0; i < this.cacheList.length; i++) {
//             await this.cacheList[i]()
//         }
//     }
// }

// const queue = new Queue();
// var delay = (timeout) => new Promise((resolve) => setTimeout(resolve, timeout))
// queue.add(() => delay(1000).then(() => console.log('task 1')))
//     .add(() => delay(2000).then(() => console.log('task 2')))
//     .add(() => delay(500).then(() => console.log('task 3')))
//     .task()


// class promiseQuene {
//     constructor(options = {}){
//         this.cacheList = [];
//         this.conCurrency = options.conCurrency;
//         this.count = 0;
//     }
//     add(fn){
//         this.cacheList.push(fn)
//         this.run();
//         return this;
//     }

//     run(){
//         if(this.count >= this.conCurrency || !this.cacheList.length) return;
//         let fn = this.cacheList.shift();
//         let promise = fn();
//         this.count++
//         promise.then(this.complateDone.bind(this)).catch(this.complateDone.bind(this))
//     }

//     complateDone(){
//         this.count--;
//         this.run()
//     }
// }

// const queue1 = new promiseQuene();
// queue1.add(() => delay(1000).then(() => console.log('task 1')))
//     .add(() => delay(2000).then(() => console.log('task 2')))
//     .add(() => delay(500).then(() => console.log('task 3')))

// // 在上诉基础上添加
// // https://frontend.devrank.cn/traffic-information/7262678295362226231
// const max = 2; // 最大并行
// const running = 0 // 正在运行的请求
// const quene = [];
// const cache = new Map();
// async function cacheRequest(url, successCallback, errorCallback){
//     if(cache.has(url)){
//        return  successCallback(cache.get(url))
//     }
//     quene.push({url, successCallback, errorCallback})
//     processQueue()
// }
// async function processQueue(){
//     if(running >= max) return;
//     if(quene.length === 0) return;
//     const requestInfo = quene.shift();
//     const {url,successCallback, errorCallback} = requestInfo;
//     running++
//     try {
//         const res = await fetch(url)
//         const data = await res.json();
//         cache.set(url, data);
//         successCallback(data);
//     } catch (error) {
//         errorCallback(error)
//     } finally{
//         running--
//         processQueue()
//     }
// }



// // 请求重试
// function request(url, maxCount){
//     return fetch(url).catch(err => maxCount <= 0 ? Promise.reject(err) : request(url, maxCount-1))
// }

// function runMicroTask(func){
//     if(typeof Promise === 'function'){
//         Promise.resolve().then(func)
//         return 
//     }

//     if(typeof MutationObserver === 'function'){
//         var ob = new MutationObserver(func);
//         let node = document.createTextNode('')
//         ob.observe(node)
//         node.data = 1
//         return
//     }

//     if(typeof process.nextTick === 'function'){
//         process.nextTick(func)
//         return 
//     }
// }


// 手写lazyman 支持链式调用
// lazyMan("dzl").log("苹果").sleep(1000).log("哈希")
// 核心思想就是将其 全部变成 宏任务

// class LazyMan {
//     constructor(name){
//         this.name = name;
//         this.task = [];

//         setTimeout(() => {
//             this.next()
//         }, 0)
//     }

//     next(){
//         const task = this.task.shift();
//         task && task()
//     }

//     log(msg){
//         const task = () => setTimeout(() => {
//                 console.log(msg)
//                 this.next()
//             }, 0)

//         this.task.push(task)
//         return this
//     }

//     sleep(time){
//         const task = () => setTimeout(() => {
//                 console.log('wait time')
//                 this.next()
//             }, time)

//         this.task.push(task)
//         return this;
//     }
// }

// new LazyMan('jiao').log('ping').sleep(5000).log('xiang')




class Logger {
    constructor(name) {
        this.name = name;
        this.task = [];

        setTimeout(() => {
            this.next()
        }, 0)
    }

    next() {
        const task = this.task.shift();
        task && task()
    }

    log(msg) {
        const task = () => setTimeout(() => {
            console.log(msg)
            this.next()
        }, 0)

        this.task.push(task)
        return this
    }

    sleep(time) {
        const task = () => setTimeout(() => {
            console.log('wait time')
            this.next()
        }, time)

        this.task.push(task)
        return this;
    }
}
const Log = new Logger()

Log.log(1).log(2).sleep(1000).log(3).sleep(500).log(4)

setTimeout(() => {
    Log.log(5).sleep(5000).log(6)
}, 1000)

new LazyMan('jiao').log('ping').sleep(5000).log('xiang')



function promisify(originalFn) {
    // 返回一个接受任意参数的函数
    return function (...args) {
        // 返回一个新的Promise
        return new Promise((resolve, reject) => {
            // 将原始函数调用包装在函数中
            function callback(err, ...results) {
                if (err) {
                    return reject(err); // 如果有错误，拒绝Promise
                }
                // 如果有多个成功值，解析为数组，否则只解析第一个值
                return resolve(results.length > 1 ? results : results[0]);
            }

            // 调用原始函数，最后一个参数是我们的自定义回调
            // 这个回调符合Node.js的错误优先回调风格
            originalFn.call(this, ...args, callback);
        });
    };
}

// 使用示例
const fs = require('fs');
const readFileAsync = promisify(fs.readFile);

readFileAsync('example.txt', { encoding: 'utf8' })
    .then(contents => {
        console.log(contents);
    })
    .catch(error => {
        console.error('An error occurred:', error);
    });



function flow(functions) {
    // 递归执行函数数组中的函数
    function execute(index) {
        // 如果执行完所有函数，退出递归
        if (index === functions.length) {
            console.log('-> done');
            return;
        }

        // 执行当前函数，并处理返回值
        const result = functions[index]();
        if (result && typeof result.then === 'function') {
            // 如果返回值是Promise，则等待它解决
            result.then(() => execute(index + 1));
        } else {
            // 如果不是Promise，直接执行下一个函数
            execute(index + 1);
        }
    }

    // 从第一个函数开始执行
    execute(0);
}

// 帮助函数，创建一个延迟Promise
function delay(seconds) {
    return new Promise(resolve => setTimeout(resolve, seconds * 1000));
}

// 使用示例
flow([
    () => console.log('-> 1'),
    () => console.log('-> 2'),
    () => delay(1).then(() => console.log('-> 3')),
    () => delay(1).then(() => console.log('-> 4')),
    () => console.log('-> 5'),
    () => console.log('-> 6'),
]);
